package poo.exo1;

import java.text.*;
import java.util.*;

import poo.Exceptions.*;

public class Banque {
       
        private List<Compte> comptes;
        private List<String> administrateurs;
        private static int comptesCrees = 0;
       
        public Banque()
        {
                this.comptes = new ArrayList<Compte>();
                this.administrateurs = new ArrayList<String>();
        }
       
        /**
         * Effectue la creation d'un compte.
         */
        public void creationCompte()
        {      
                Scanner clavier = new Scanner(System.in);

                System.out.println("Creation d'un compte...\n");
                System.out.println("Nom du detenteur ?\n");
               
                String nom = clavier.nextLine();
               
                //Le numero de compte est égal au nombre de compte de la banque +1
                int numCompte = comptesCrees+1;
               
                System.out.println("Quel type de compte ?\n");
                System.out.println("1.Compte Epargne");
                System.out.println("2.Compte Courant");
                System.out.println("3.Compte Action");
               
                int choix = clavier.nextInt();
               
                //Solde initial du compte
                System.out.println("Solde initial?\n");
                double solde = clavier.nextDouble();

                switch(choix)
                {
                        case 1 :
                                //Minimum sur operations de cr�dit sp�cifi� � la creation et non modifiable
                                System.out.println("Minimum sur operations de credit ?\n");
                                double minimumCredit = clavier.nextDouble();

                                try{
                                        CompteEpargne ce = new CompteEpargne(nom, numCompte, solde, minimumCredit);
                                        comptes.add(ce);
                                        comptesCrees++;
                                        System.out.println(ce);

                                }
                                catch(SoldeMinimumRequis e){
                                        System.out.println(e+" Valeur entr�e : "+e.getVersementMinimum()+"\n");
                                }
                                break;
                        case 2 :
                                //Plancher negatif � specifier
                                System.out.println("Plancher n�gatif ?\n");
                                double plancher = clavier.nextDouble();
                               
                                CompteCourant cc;
                                cc = new CompteCourant(nom, numCompte, solde, plancher);
                               
                                comptes.add(cc);
                                comptesCrees++;
                                System.out.println(cc);
                                break;
                        case 3 :
                                //Plafond � specifier
                                System.out.println("Plafond pour les operations de cr�dit?\n");
                                double plafond = clavier.nextDouble();
                               
                                CompteAction ca;
                               
                                try{
                                        ca = new CompteAction(nom, numCompte, solde, plafond);
                                        comptes.add(ca);
                                        comptesCrees++;
                                        System.out.println(ca);
                                }
                                catch(SoldeMinimumRequis e){
                                        System.out.println(e+" Valeur entr�e : "+e.getVersementMinimum()+"\n");
                                }
                                break;
                }
        //FIN CREATION COMPTE
        }
        /**
         * Liste les comptes de l'utilisateur.
         * @param nom nom du detenteur des comptes.
         */
        public void listerComptes(String nom){
                String ce, cc, ca;
                ce = "Comptes Epargne :\n";
                cc = "\nComptes Courant :\n";
                ca = "\nComptes Action :\n";
                for(Compte temp : this.comptes){
                        if(temp.getNom().equals(nom)){
                                if(temp instanceof CompteEpargne)
                                        ce = ce + temp.toString();
                                if(temp instanceof CompteCourant)
                                        cc = cc + temp.toString();
                                if(temp instanceof CompteAction)
                                        ca = ca + temp.toString();
                        }
                }
                System.out.println("Comptes de "+nom+":\n"+ce+cc+ca);
        }
        /**
         * Liste les comptes de la banque.
         */
        public void listerComptesBanque()
        {
                if(this.comptes.isEmpty()){
                        System.out.println("Pas de compte ouvert à ce jour");
                }
                else
                {
                        System.out.println("LISTE DES COMPTES DE LA BANQUE");
                        for(Compte temp : this.comptes){
                                System.out.println(temp.toString());
                        }
                }
        }
        /**
         * Effectue une operation de crédit sur le compte.
         * @param c compte sur lequel est effectué l'operation de crédit.
         * @param somme somme à ajouter au compte.
         */
        public void creditCompte(Compte c, double somme){
               
                if(c instanceof CompteEpargne)
                {
                        try
                        {
                                if( (((CompteEpargne) c).getMinimumCredit()) < somme )
                                                throw new CreditNonAutorise("Crédit non autorisée, minimum sur les operations de crédit : "+((CompteEpargne) c).getMinimumCredit(), somme);
                                c.solde += somme;
                                System.out.println(c);
                        }
                        catch(CreditNonAutorise e){
                                System.out.println(e);
                        }
                }
                if(c instanceof CompteAction)
                {
                        try
                        {
                                if( (((CompteAction) c).getPlafondCredit()) < somme )
                                                throw new CreditNonAutorise("Crédit non autorisée, plafond sur les operations de crédit : "+((CompteAction) c).getPlafondCredit(), somme);
                                c.solde += somme;
                                System.out.println(c);
                        }
                        catch(CreditNonAutorise e){
                                System.out.println(e);
                        }
                }
        }
        /**
         * Effectue une operation de débit sur le compte.
         * @param c compte sur lequel est effectué l'operation de débit.
         * @param somme somme à retirer au compte.
         */
        public void debitCompte(Compte c, double somme){
               
                if(c instanceof CompteCourant)
                {
                        try
                        {
                                if( (((CompteCourant) c).getPlancher()*-1) > (c.solde - somme) )
                                                throw new DebitNonAutorise("Débit non autorisée, en dessous du plancher", somme);
                                c.setSolde(c.getSolde() - somme);
                                System.out.println(c);
                        }
                        catch(DebitNonAutorise e){
                                System.out.println(e);
                        }
                }
                else
                {
                        try
                        {
                                if(c instanceof CompteAction)
                                                throw new DebitNonAutorise("Débit non autorisée sur ce type de compte", somme);
                                c.setSolde(c.getSolde() - somme);
                                System.out.println(c);
                        }
                        catch(DebitNonAutorise e){
                                System.out.println(e);
                        }
                        finally
                        {
                                System.out.println("Souhaitez-vous lever les actions (cela entraine la fermeture du compte)  y ou n");
                                Scanner clavier = new Scanner(System.in);
                                String choix = clavier.nextLine();
                               
                                if(choix.equalsIgnoreCase("y")){
                                        if(this.cloturerCompte(c))
                                                System.out.println("\n Compte fermé...\n");
                                }
                        }
                }
        }
        /**
         * Effectue un virement d'un compte vers un autre.
         * @param compteEmetteur Compte emetteur de fonds.
         * @param compteDestination Compte recepteur de fonds.
         * @param somme Fonds à transferer sur l'autre compte.
         */
        public void virementCompteToCompte(Compte compteEmetteur, Compte compteDestination, double somme)
        {
                try{
                        if( compteEmetteur instanceof CompteAction)
                        {
                                if(compteDestination instanceof CompteAction){
                                        throw new Exception("Le virement ne peut s'effectuer sur un compte action");
                                }
                                else if( (compteEmetteur.getSolde() - somme) < 0 || (compteEmetteur.getSolde() - somme) < CompteAction.getVersementInitial())
                                {
                                        throw new DebitNonAutorise("Virement non autorisé, le solde devient inferieur au minimum initial("+CompteAction.getVersementInitial()+")", somme);
                                }
                        }
                        else
                        {
                                this.debitCompte(compteEmetteur, somme);
                                this.creditCompte(compteDestination, somme);
                        }
                }
                catch(Exception e){
                        System.out.println(e);
                }
        }
        /**
         * Calcul le taux d'interet d'un compte epargne.
         * @param ce Compte Epargne sur lequel calculer les interets.
         */
        public void calculerInteret(CompteEpargne ce){
                // On recupere le numero du mois courant
                DateFormat dateFormat = new SimpleDateFormat("MM");
                Date date = new Date();
                int mois = Integer.parseInt(dateFormat.format(date));
               
                //Puis on calcul le taux d'interet à ce mois
                double solde = ce.getSolde();
                double txInteret = CompteEpargne.getTauxInteret()/100;
                double interets = ((solde * txInteret) /12) * mois;
               
                ce.setSolde(ce.getSolde()+ interets);
        }
        /**
         * Affiche le solde d'un compte.
         * @param c Compte dont on souhaite afficher le solde.
         */
        public void afficherSolde(Compte c){
                System.out.println("\nSolde du compte"+c.getSolde()+"\n");
        }
        /**
         * Effectue la fermeture d'un compte.
         * @param c Compte que l'on souhaite cloturer.
         * @return boolean true si tout s'est bien passer
         */
        public boolean cloturerCompte(Compte c){
                return this.comptes.remove(c);
        }
       
        /**
         * Retourne la liste des administrateurs.
         * @return List liste des administrateurs.
         */
        public List<String> getAdministrateurs()
        {
                return this.administrateurs;
        }
        /**
         * Retourne un compte correspondant au numero entré en parametre.
         * @param numero Numero du compte.
         * @return Compte correspondant au numero.
         */
        public Compte getCompte(int numero){
               
                for(Compte temp : this.comptes){
                        if(temp.getNumero() == numero)
                                return temp;
                }
                return null;
        }

}
